#!/bin/bash
#
# Copyright (c) 2024 Institute of Software, CAS.
# Author : Tan Xiaofan <xiaofan@iscas.ac.cn>
#

binpath="$1"
libpath="$2"
libpath_install="$3"
rpath="$4"

elfcheck(){
    local magic=$(head -c4 "$1" | xxd -p)
    if [ "$magic" = "7f454c46" ]; then
        return 0
    else
        return 1
    fi
}

elfneeds(){
    local file="$1"
    local needs=$(readelf -d "$file" | grep NEEDED | awk '{print $NF}')
    local need
    for need in $needs; do
        # check need format like [xxx]
        if [ "${need:0:1}${need: -1}" = "[]" ]; then
            basename "${need:1: -1}"
        fi
    done
}

lookupsharelib(){
    if [ -e "$libpath/$1" ]; then
        return 0
    else
        return 1
    fi
}

hadneed(){
    [[ "$needs" = *" $1 "* ]]
    return $?
}

additemtoneeds(){
    if ! hadneed "$1"; then
        needs="$needs$1 "
    fi
}

addtoneeds(){
    local need="$1"
    if hadneed "$need"; then
        return
    fi
    additemtoneeds "$need"
    while [ -L "$libpath/$need" ]; do
        need=$(readlink "$libpath/$need")
        need=$(basename "$need")
        if ! lookupsharelib "$need"; then
            break
        fi
        additemtoneeds "$need"
    done

    for need in $(elfneeds "$libpath/$1"); do
        if lookupsharelib "$need"; then
            addtoneeds "$need"
        fi
    done
}

main(){
    local bin need
    for bin in $(find "$binpath" -type f); do
        if elfcheck "$bin"; then
            for need in $(elfneeds "$bin"); do
                if lookupsharelib "$need"; then
                    addtoneeds "$need"
                fi
            done
            patchelf --set-rpath "$rpath" "$bin"
        fi
    done
    for need in $needs; do
        cp -a "$libpath/$need" "$libpath_install"
    done
}

main
